package errors

import (
	"fmt"
	"runtime"
	"strings"
)

// ErrorCode 错误码类型
type ErrorCode int

const (
	// 系统级错误码 (1000-1999)
	SystemError   ErrorCode = 1000
	DatabaseError ErrorCode = 1001
	CacheError    ErrorCode = 1002
	NetworkError  ErrorCode = 1003
	ConfigError   ErrorCode = 1004

	// 业务级错误码 (2000-2999)
	BusinessError   ErrorCode = 2000
	ValidationError ErrorCode = 2001
	AuthError       ErrorCode = 2002
	PermissionError ErrorCode = 2003
	NotFoundError   ErrorCode = 2004
	DuplicateError  ErrorCode = 2005

	// 客户端错误码 (4000-4999)
	BadRequestError      ErrorCode = 4000
	UnauthorizedError    ErrorCode = 4001
	ForbiddenError       ErrorCode = 4003
	NotFoundClientError  ErrorCode = 4004
	RequestTimeoutError  ErrorCode = 4008
	TooManyRequestsError ErrorCode = 4029

	// 便利别名
	InvalidParams = ValidationError
	NotFound      = NotFoundError

	// 服务器错误码 (5000-5999)
	InternalServerError ErrorCode = 5000
	ServiceUnavailable  ErrorCode = 5003
	GatewayTimeout      ErrorCode = 5004
)

// AppError 应用错误结构
type AppError struct {
	Code    ErrorCode              `json:"code"`
	Message string                 `json:"message"`
	Details string                 `json:"details,omitempty"`
	Cause   error                  `json:"-"`
	Stack   string                 `json:"-"`
	Context map[string]interface{} `json:"context,omitempty"`
}

// Error 实现 error 接口
func (e *AppError) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("[%d] %s: %s", e.Code, e.Message, e.Cause.Error())
	}
	return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}

// Unwrap 实现 errors.Unwrap
func (e *AppError) Unwrap() error {
	return e.Cause
}

// WithContext 添加上下文信息
func (e *AppError) WithContext(key string, value interface{}) *AppError {
	if e.Context == nil {
		e.Context = make(map[string]interface{})
	}
	e.Context[key] = value
	return e
}

// WithDetails 添加详细信息
func (e *AppError) WithDetails(details string) *AppError {
	e.Details = details
	return e
}

// GetHTTPCode 获取对应的HTTP状态码
func (e *AppError) GetHTTPCode() int {
	switch e.Code {
	case BadRequestError, ValidationError:
		return 400
	case UnauthorizedError, AuthError:
		return 401
	case ForbiddenError, PermissionError:
		return 403
	case NotFoundError, NotFoundClientError:
		return 404
	case RequestTimeoutError:
		return 408
	case DuplicateError:
		return 409
	case TooManyRequestsError:
		return 429
	case InternalServerError, SystemError, DatabaseError, CacheError:
		return 500
	case ServiceUnavailable:
		return 503
	case GatewayTimeout:
		return 504
	default:
		return 500
	}
}

// 创建错误的便利函数

// NewSystemError 创建系统错误
func NewSystemError(message string) *AppError {
	return &AppError{
		Code:    SystemError,
		Message: message,
		Stack:   getStack(),
	}
}

// NewBusinessError 创建业务错误
func NewBusinessError(message string) *AppError {
	return &AppError{
		Code:    BusinessError,
		Message: message,
		Stack:   getStack(),
	}
}

// NewValidationError 创建验证错误
func NewValidationError(message string, details ...string) *AppError {
	err := &AppError{
		Code:    ValidationError,
		Message: message,
		Stack:   getStack(),
	}
	if len(details) > 0 {
		err.Details = details[0]
	}
	return err
}

// NewAuthError 创建认证错误
func NewAuthError(message string) *AppError {
	return &AppError{
		Code:    AuthError,
		Message: message,
		Stack:   getStack(),
	}
}

// NewNotFoundError 创建资源不存在错误
func NewNotFoundError(message string) *AppError {
	return &AppError{
		Code:    NotFoundError,
		Message: message,
		Stack:   getStack(),
	}
}

// NewInternalError 创建内部服务器错误
func NewInternalError(message string) *AppError {
	return &AppError{
		Code:    InternalServerError,
		Message: message,
		Stack:   getStack(),
	}
}

// NewDatabaseError 创建数据库错误
func NewDatabaseError(message string, cause error) *AppError {
	return &AppError{
		Code:    DatabaseError,
		Message: message,
		Cause:   cause,
		Stack:   getStack(),
	}
}

// NewDuplicateError 创建重复错误
func NewDuplicateError(message string) *AppError {
	return &AppError{
		Code:    DuplicateError,
		Message: message,
		Stack:   getStack(),
	}
}

// WrapError 包装现有错误
func WrapError(code ErrorCode, message string, cause error) *AppError {
	return &AppError{
		Code:    code,
		Message: message,
		Cause:   cause,
		Stack:   getStack(),
	}
}

// IsAppError 判断是否为应用错误
func IsAppError(err error) bool {
	_, ok := err.(*AppError)
	return ok
}

// GetAppError 获取应用错误
func GetAppError(err error) (*AppError, bool) {
	appErr, ok := err.(*AppError)
	return appErr, ok
}

// getStack 获取调用栈信息
func getStack() string {
	var buf strings.Builder
	pcs := make([]uintptr, 10)
	n := runtime.Callers(3, pcs) // 跳过当前函数和调用者

	frames := runtime.CallersFrames(pcs[:n])
	for {
		frame, more := frames.Next()
		if !strings.Contains(frame.File, "runtime/") {
			buf.WriteString(fmt.Sprintf("%s:%d %s\n", frame.File, frame.Line, frame.Function))
		}
		if !more {
			break
		}
	}

	return buf.String()
}

// 错误消息常量
const (
	MsgSystemError     = "系统错误"
	MsgDatabaseError   = "数据库错误"
	MsgCacheError      = "缓存错误"
	MsgNetworkError    = "网络错误"
	MsgConfigError     = "配置错误"
	MsgBusinessError   = "业务错误"
	MsgValidationError = "参数验证失败"
	MsgAuthError       = "认证失败"
	MsgPermissionError = "权限不足"
	MsgNotFoundError   = "资源不存在"
	MsgDuplicateError  = "资源已存在"
	MsgInternalError   = "内部服务器错误"
)
